package com.msb.mall.product.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.msb.common.constant.ProductConstant;
import com.msb.common.dao.MemberPrice;
import com.msb.common.dao.SkuHasStockDto;
import com.msb.common.dao.SkuReductionDTO;

import com.msb.common.dao.SpuBoundsDTO;
import com.msb.common.dao.es.SkuESModel;
import com.msb.common.utils.R;
import com.msb.mall.product.entity.*;
import com.msb.mall.product.fegin.couponFeginService;
import com.msb.mall.product.fegin.searchFeginService;
import com.msb.mall.product.fegin.wareFeginService;
import com.msb.mall.product.service.*;
import com.msb.mall.product.vo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.msb.common.utils.PageUtils;
import com.msb.common.utils.Query;

import com.msb.mall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    SpuImagesService spuImagesService;

    //基本属性（规格参数）
    @Autowired
    ProductAttrValueService productAttrValueService;

    @Autowired
    AttrService attrService;

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    SkuImagesService skuImagesService;

    //销售属性
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    couponFeginService couponFeginService;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    wareFeginService wareFeginService;

    @Autowired
    searchFeginService searchFeginService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }


    /**
     * SPU信息检索
     * 分页查询
     * 分类 品牌 状态 关键字查询
     *
     * @param params
     * @return status=&key=&brandId=0&catelogId=0&page=1&limit=10
     *
     * 查询什么都不写的时候，有时会带默认值，也什么都不带，像商品库存查询就没带
     */
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        // 设置对应的检索条件
        // 1. 关键字查询
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and((obj) -> {
                obj.eq("id", key).or()
                        .like("spu_name", key)
                        .like("spu_description", key);
            });
        }
        // status
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            wrapper.eq("publish_status", status);
        }

        // brandId
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
            wrapper.eq("brand_id", brandId);
        }

        //catelogId
        String catelogId = (String) params.get("catalogId");
        if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
            wrapper.eq("catalog_id", catelogId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper);

        //根据查询到的分页信息，查询出类别的名字和品牌的名字
        List<SpuInfoEntity> records = page.getRecords();
        List<spuinfoVO> collect = records.stream().map((spu) -> {
            CategoryEntity categoryById = categoryService.getById(spu.getCatalogId());
            BrandEntity brandById = brandService.getById(spu.getBrandId());
            spuinfoVO spuinfoVO = new spuinfoVO();
            BeanUtils.copyProperties(spu, spuinfoVO);
            spuinfoVO.setBrandName(brandById.getName());
            spuinfoVO.setCatalogName(categoryById.getName());

            return spuinfoVO;
        }).collect(Collectors.toList());
        IPage<spuinfoVO> page1 = new Page<>();
        page1.setRecords(collect);
        page1.setPages(page.getPages());
        page1.setCurrent(page.getCurrent());

        return new PageUtils(page1);
    }


    @Transactional
    @Override
    public void saveSpuInfo(spuinfoVO spuinfoVO) {

        //1.保存spu基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity=new SpuInfoEntity();
        BeanUtils.copyProperties(spuinfoVO,spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        spuInfoEntity.setPublishStatus(0);//设置为新建状态
        this.save(spuInfoEntity);

        //2.保存spu的商品介绍(也就是图片地址)pms_spu_info_desc
        //todo https://dobaosc-mall.oss-cn-guangzhou.aliyuncs.com/2022-10-06//969525ee-57f6-44d8-8338-2dbd57fc68e7_0d40c24b264aa511.jpg,https://dobaosc-mall.oss-cn-guangzhou.aliyuncs.com/2022-10-06//6fe53930-0c40-4a51-8882-8c2ed4a909a9_3c24f9cd69534030.jpg
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        //获取多个图片地址集合
        List<String> decript = spuinfoVO.getDecript();
        //把多个图片地址用 逗号 分开
        String join = String.join(",", decript);
        spuInfoDescEntity.setDecript(join);
        spuInfoDescService.save(spuInfoDescEntity);

        //3.保存spu图集信息pms_spu_images
        // 这里也可以向上面一样用逗号隔开，只储存一个字段到数据库
        List<String> images = spuinfoVO.getImages();
        //将多个图片封装成一个个的spuImagesEntity实体类对象
        final List<SpuImagesEntity> list = images.stream().map((item) -> {
            SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
            spuImagesEntity.setImgUrl(item);
            spuImagesEntity.setSpuId(spuInfoEntity.getId());
            return spuImagesEntity;
        }).collect(Collectors.toList());
        spuImagesService.saveBatch(list);

        //4.保存规格参数pms_spu_product_attr_value
        List<BaseAttrs> baseAttrs = spuinfoVO.getBaseAttrs();
        List<ProductAttrValueEntity> collect = baseAttrs.stream().map((attr) -> {
            ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
            productAttrValueEntity.setAttrId(attr.getAttrId());
            productAttrValueEntity.setAttrValue(attr.getAttrValues());
            productAttrValueEntity.setSpuId(spuInfoEntity.getId());
            productAttrValueEntity.setQuickShow(attr.getShowDesc());
            //根据属性id获取属性的名字
            AttrEntity attrEntity = attrService.getById(attr.getAttrId());
            productAttrValueEntity.setAttrName(attrEntity.getAttrName());
            return productAttrValueEntity;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(collect);

        //5.保存当前spu对应的所有sku的信息
        List<Skus> skus = spuinfoVO.getSkus();
        //5.1保存sku基本信息pms_sku_info
        if (skus!=null && skus.size()>0){
           skus.forEach((m) -> {
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(m, skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSaleCount(0L);

                List<Images> images1 = m.getImages();
                String defaultimg = null;
                for (Images images2 : images1) {
                    if (images2.getDefaultImg() == 1) {
                        //表示的是默认图集
                        defaultimg = images2.getImgUrl();
                    }
                }
                skuInfoEntity.setSkuDefaultImg(defaultimg);
                skuInfoService.save(skuInfoEntity);

                //5.2保存sku图片信息(这里保存的就是默认图集的信息)pms_sku_images
               List<SkuImagesEntity> skuImagesEntities = images1.stream().map((img) -> {

                   SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                   BeanUtils.copyProperties(img, skuImagesEntity);
                   skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                   return skuImagesEntity;
               }).filter(img -> {
                   //把不是默认图集信息的过滤掉
                   return img.getDefaultImg()==1;  // TODO 为空的图片不需要保存
               }).collect(Collectors.toList());
                skuImagesService.saveBatch(skuImagesEntities);


               //5.3保存满减信息，折扣，会员价，mall_sms: sms_sku_ladder sms_full_reduction  sms_member_price
               SkuReductionDTO skuReductionDTO=new SkuReductionDTO();
               BeanUtils.copyProperties(m, skuReductionDTO);
               skuReductionDTO.setSkuId(skuInfoEntity.getSkuId());

               //设置会员价
               if (m.getMemberPrice()!=null && m.getMemberPrice().size()>0){
                   List<MemberPrice> memberPrices = m.getMemberPrice().stream().map((memberPrice) -> {
                       MemberPrice mdto = new MemberPrice();
                       BeanUtils.copyProperties(memberPrice, mdto);
                       return mdto;
                   }).collect(Collectors.toList());
                   skuReductionDTO.setMemberPrice(memberPrices);
               }
              R r= couponFeginService.saveFullReductionInfo(skuReductionDTO);
                if (r.getcode()!=0){
                    log.error("调用Coupon服务处理满减、折扣，会员价操作失败...");
                }

               //5.4sku销售属性信息pms_sku_sale_attr_value
               List<Attr> attrs = m.getAttr();
               List<SkuSaleAttrValueEntity> saleAttrValueEntities = attrs.stream().map(sale -> {
                   SkuSaleAttrValueEntity entity = new SkuSaleAttrValueEntity();
                   BeanUtils.copyProperties(sale, entity);
                   entity.setSkuId(skuInfoEntity.getSkuId());
                   return entity;
               }).collect(Collectors.toList());
               skuSaleAttrValueService.saveBatch(saleAttrValueEntities);

           });
        }

        //6.保存spu的积分信息mall-sms: sms_spu_bounds
        Bounds bounds = spuinfoVO.getBounds();
        SpuBoundsDTO spuBoundsDTO = new SpuBoundsDTO();
        BeanUtils.copyProperties(bounds, spuBoundsDTO);
        spuBoundsDTO.setSpuid(spuInfoEntity.getId());
       R r= couponFeginService.saveSpuBounds(spuBoundsDTO);
       if (r.getcode()!=0){
           log.error("调用Coupon服务存储积分信息操作失败");

       }
    }


    /**
     * 实现商品上架--》商品相关数据存储到ElasticSearch中
     * 1.根据SpuID查询出相关的信息
     *   封装到对应的对象中
     * 2.将封装的数据存储到ElasticSearch中--》调用mall-search的远程接口
     * 3.更新SpuID对应的状态--》上架
     *
     * @param spuId
     */

    @Override
    public void up(Long spuId) {
        // 1.根据spuId查询相关的信息 封装到SkuESModel对象中
        List<SkuESModel> skuEs = new ArrayList<>();
        // 根据spuID找到对应的SKU信息
        List<SkuInfoEntity> skus = skuInfoService.getskusByspu(spuId);

        // 对应的规格参数  根据spuId来查询规格参数信息
        List<SkuESModel.Attrs> attrsModel = getAttrsModel(spuId);
        // 需要根据所有的skuId获取对应的库存信息---》远程调用
        List<Long> skuIds = skus.stream().map(sku -> {
            return sku.getSkuId();
        }).collect(Collectors.toList());
        Map<Long, Boolean> skusHasStockMap = getSkusHasStock(skuIds);
        // 2.远程调用mall-search的服务，将SukESModel中的数据存储到ES中
        List<SkuESModel> skuESModels = skus.stream().map(item -> {
            SkuESModel model = new SkuESModel();
            // 先实现属性的复制
            BeanUtils.copyProperties(item,model);
            model.setSubTitle(item.getSkuTitle());
            model.setSkuPrice(item.getPrice());
            model.setSkuImg(item.getSkuDefaultImg());

            // hasStock 是否有库存 --》 库存系统查询  一次远程调用获取所有的skuId对应的库存信息
            if(skusHasStockMap == null){
                model.setHasStock(true);
            }else{
                model.setHasStock(skusHasStockMap.get(item.getSkuId()));
            }
            // hotScore 热度分 --> 默认给0即可
            model.setHotScore(0l);
            // 品牌和类型的名称
            BrandEntity brand = brandService.getById(item.getBrandId());
            CategoryEntity category = categoryService.getById(item.getCatalogId());
            model.setBrandName(brand.getName());
            model.setBrandImg(brand.getLogo());
            model.setCatalogName(category.getName());
            // 需要存储的规格数据
            model.setAttrs(attrsModel);

            return model;
        }).collect(Collectors.toList());
        // 将SkuESModel中的数据存储到ES中
        R r = searchFeginService.productStatusUp(skuESModels);
        // 3.更新SPUID对应的状态
        // 根据对应的状态更新商品的状态

        if(r.getcode() == 0){
            // 远程调用成功  更新商品的状态为 上架
            baseMapper.updateSpuStatusUp(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        }else{
            // 远程调用失败
        }
    }

    @Override
    public List<OrderItemSpuInfoVO> getOrderItemSpuInfoBySpuId(Long[] spuIds) {

       List<OrderItemSpuInfoVO> SpuInfoVOS = new ArrayList<>();

        for (Long spuId : spuIds) {
            OrderItemSpuInfoVO orderItemSpuInfoVO = new OrderItemSpuInfoVO();
            SpuInfoEntity spuInfoEntity = this.getById(spuId);
            orderItemSpuInfoVO.setId(spuId);
            orderItemSpuInfoVO.setSpuName(spuInfoEntity.getSpuName());
            orderItemSpuInfoVO.setSpuDescription(spuInfoEntity.getSpuDescription());
            orderItemSpuInfoVO.setCatalogId(spuInfoEntity.getCatalogId());
            orderItemSpuInfoVO.setBrandId(spuInfoEntity.getBrandId());
            //获取spu的图片信息
            SpuInfoDescEntity spuInfoDescServiceById = spuInfoDescService.getById(spuId);
            orderItemSpuInfoVO.setImg(spuInfoDescServiceById.getDecript());
            //获取品牌的信息
            BrandEntity byId = brandService.getById(spuInfoEntity.getBrandId());
            orderItemSpuInfoVO.setBrandName(byId.getName());
            //获取分类的信息
            CategoryEntity categoryServiceById = categoryService.getById(spuInfoEntity.getCatalogId());
            orderItemSpuInfoVO.setCatalogName(categoryServiceById.getName());
            SpuInfoVOS.add(orderItemSpuInfoVO);
        }


        return SpuInfoVOS;
    }


    /**
     * 根据skuIds获取对应的库存状态
     * @param skuIds
     * @return
     */
    private Map<Long, Boolean> getSkusHasStock(List<Long> skuIds) {

        List<SkuHasStockDto> skusHasStock =null;
        //判断获取的skuid是否为空
        if (skuIds == null && skuIds.size() == 0) {
            return null;
        }
        try {
            // 调用远程接口获取对应的信息
            skusHasStock = wareFeginService.getSkusHasStock(skuIds);
            //skusHasStock.stream().collect(Collectors.toMap(item->{return item.getSkuId();},item->{return item.getHasStock();}));
            Map<Long, Boolean> map = skusHasStock.stream()
                    .collect(Collectors.toMap(SkuHasStockDto::getSkuId, item -> item.getHasStock()));
            return map;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据spuid找到对应的规格参数（基本属性）
     * @param spuId
     * @return
     */
    private List<SkuESModel.Attrs> getAttrsModel(Long spuId) {

        // 1. product_attr_value中 存储了对应的spu相关的所有的规格参数
        List<ProductAttrValueEntity> productAttrValueEntities
                = productAttrValueService.getattrByspuid(spuId);

        // 2. attrEntity中  search_type 决定该属性是否支持检索  0-不需要，1-需要
        //获取所有规格参数的属性id
        List<Long> basearrtIds = productAttrValueEntities.stream().map((m) -> {
            return m.getAttrId();
        }).collect(Collectors.toList());
        // 查询出所有的可以检索的对应的规格参数编号
        List<Long> searchAttrIds=attrService.selectSearchAttrIds(basearrtIds);
        //把 productAttrValueEntities中，不可以检索的数据过滤
        List<SkuESModel.Attrs> attrsModel = productAttrValueEntities.stream().filter((item) -> {
            //item.getAttrId()是否包含在basearrtIds
            return basearrtIds.contains(item.getAttrId());
        }).map((m -> {
            SkuESModel.Attrs attrs = new SkuESModel.Attrs();
            /*attrs.setAttrId(item.getAttrId());
            attrs.setAttrName(item.getAttrName());
            attrs.setAttrValue(item.getAttrValue());*/
            BeanUtils.copyProperties(m, attrs);
            return attrs;
        })).collect(Collectors.toList());


        return attrsModel;
    }
}